package com.backstage.configuration.shiro;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.backstage.service.UserService;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.Resource;
import java.util.LinkedHashMap;

/**
 * @Project authority
 * @Package com.backstage.configuration.shiro
 * @Data 2017/7/11下午 5:25.
 * @Aurhor 阮雪峰
 */
@Configuration
public class ShiroConfig {


    /**
     * shiro缓存管理器;
     * 需要注入对应的其它的实体类中：
     * 1、安全管理器：securityManager
     * 可见securityManager是整个shiro的核心；
     * @return
     */
    @Bean
    public EhCacheManager ehCacheManager(){
        //System.out.println("ShiroConfiguration.getEhCacheManager()");
        EhCacheManager cacheManager = new EhCacheManager();
        cacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
        return cacheManager;
    }

    /**
     * shiroFilter
     * @param manager
     * @return
     */
    @Bean(name="shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(manager);
        // 配置登录的url
        bean.setLoginUrl("/login.html");
        //bean.setSuccessUrl("/index.html");
        // 过滤链
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/authority/**", "anon"); // 表示可以匿名访问
        filterChainDefinitionMap.put("/layuicms/**", "anon"); // 表示可以匿名访问
        filterChainDefinitionMap.put("/js/**", "anon"); // 表示可以匿名访问
        filterChainDefinitionMap.put("/plugin/**", "anon"); // 表示可以匿名访问
        filterChainDefinitionMap.put("/common/**", "anon"); // 表示可以匿名访问
        filterChainDefinitionMap.put("/error/**", "anon"); // 表示可以匿名访问
        //filterChainDefinitionMap.put("/**.html", "anon"); // 表示可以匿名访问
        filterChainDefinitionMap.put("/**.html", "authc");// 管理员权限需要验证过滤
        filterChainDefinitionMap.put("/**", "authc");// 管理员权限需要验证过滤

        bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return bean;
    }

    /**
     * 注册自定义的Realm
     * @return
     */
    @Bean(name="authorityRealm")
    public AuthorityRealm myRealm() {
        AuthorityRealm realm = new AuthorityRealm();
        realm.setCredentialsMatcher(new CustomCredentialsMatcher());
        return realm;
    }

    /**
     * 声明SecurityManager
     * @param authorityRealm
     * @return
     */
    @Bean(name="securityManager")
    public SecurityManager securityManager(@Qualifier("authorityRealm") AuthorityRealm authorityRealm) {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(authorityRealm);
        manager.setCacheManager(ehCacheManager());
        return manager;
    }


    /**
     * 保证实现了shiro内部lifecycle函数的bean执行
     * @return
     */
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }


    /**
     * 开启shiro,首先创建代理
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator creator=new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }

    /**
     * 再加载securityManager
     * @param manager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager manager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(manager);
        return advisor;
    }

    /**
     * ShiroDialect，为了在thymeleaf里使用shiro的标签的bean
     * @return
     */
    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }
}
